#include "book.h"
#include "ui_book.h"

#include<alibabacloud\oss\OssClient.h>
#include <iostream>

#include <QUrl>
#include<QObject>
#include<QFile>
#include<QThread>
#include<QTextStream>
#include<QQueue>
#include<QFileInfo>
#include <QNetworkAccessManager>
#include<QNetworkReply>
#include<QNetworkRequest>
#include <QFileDialog>
#include <QIcon>
#include <QEventLoop>
#include <QTimer>
#include <QCryptographicHash>
#include <QMessageBox>
#include <QModelIndex>
#include<QStandardItem>
#include <QStandardItemModel>
#include <QStringListModel>
#include <Qpair>
#include <iostream>
using namespace AlibabaCloud::OSS;
Book::Book(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Book)
{
    /* 初始化OSS账号信息 */
    /* 填写Bucket所在地域对应的Endpoint。以华东1（杭州）为例，Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    Endpoint = "https://oss-cn-beijing.aliyuncs.com";
    /* 填写Bucket名称，例如examplebucket。*/
    BucketName= "xiexuxin";
    Region = "cn-beijing";
    /* 初始化网络等资源。*/
    InitializeSdk();
    conf.signatureVersion = SignatureVersionType::V4;
    conf.verifySSL = false;
    
    //初始化ui界面
    ui->setupUi(this);
    ui->urledit->setText("https://vscode.download.prss.microsoft.com/dbazure/download/stable/38c31bc77e0dd6ae88a4e9cc93428cc27a56ba40/VSCodeUserSetup-x64-1.93.1.exe");
    ui->progressBar_2->setValue(0);
    //槽函数绑定，url获取
    connect(ui->urlbtn,&QPushButton::clicked,this,&Book::urlbtn_clicked);
    //存储路径获取
    connect(ui->filepathbtn,&QPushButton::clicked,this,&Book::filepathbtn_clicked);
    //文件下载
    connect(ui->downloadBtn, &QPushButton::clicked, this, [=]() {
        downLoadAction(QUrl(ui->urledit->text()));
        });
    fileListShow(); 
    


}

Book::~Book()
{
    delete ui;
}
void Book::changeProgressValue(int64_t value, int64_t filesize)
{
    ui->progressBar_2->setValue((value * 100) / filesize);
}

void Book::downLoadAction(const QUrl url)
{


    QTimer* timer = new QTimer(this);
    /* 填写Object完整路径，完整路径中不能包含Bucket名称，例如exampledir/exampleobject.txt。*/
    std::string ObjectName = "file/VirtualBox-7.0.18-162988-Win.exe";
    /* 下载Object到本地文件examplefile.txt，并保存到指定的本地路径中（D:\\localpath）。如果指定的本地文件存在会覆盖，不存在则新建。*/
    /* 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。*/
    /* 设置断点记录文件所在的目录，并确保指定的目录已存在，例如D:\\localpath。*/
    /* 只有当Object下载中断产生了断点记录文件后，如果需要继续下载该Object，才需要设置对应的断点记录文件。下载完成后，该文件会被删除。*/
    /* yourRegion填写Bucket所在地域对应的Region。以华东1（杭州）为例，Region填写为cn-hangzhou。*/
        /* 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    QFile file(QString::fromStdString(DownloadFilePath));
    if (file.exists()) {
        file.remove();
    }
    
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
 
    ///* 断点续传下载。*/
    DownloadObjectRequest request(BucketName, ObjectName, DownloadFilePath, CheckpointFilePath);
    auto outcome = client.ResumableDownloadObject(request);

    if (!outcome.isSuccess()) {
        /* 异常处理。*/
        std::cout << "ResumableDownloadObject fail" <<
            ",code:" << outcome.error().Code() <<
            ",message:" << outcome.error().Message() <<
            ",requestId:" << outcome.error().RequestId() << std::endl;
        return ;
    }
    else {
        
        connect(timer, &QTimer::timeout, this, [&]() {
            // 随机增加进度，模仿非匀速增加
            int increment = rand() % 10; // 随机增加 0-9
            currentoffset += increment;

            if (currentoffset >= 100) {
                currentoffset = 100; // 确保不会超过 100
                timer->stop(); // 停止定时器
            }

            ui->progressBar_2->setValue(currentoffset);
            });
        timer->start(100); // 每 100 毫秒更新一次
        QMessageBox::information(this, "下载", "下载成功");
        
    }
   
    

}
void Book::fileListShow()
{
    /* 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
    /* 列举文件。*/
  ListObjectsRequest request(BucketName);
  auto outcome = client.ListObjects(request);

  if (!outcome.isSuccess()) {
      /* 异常处理。*/
      std::cout << "ListObjects fail" <<
          ",code:" << outcome.error().Code() <<
          ",message:" << outcome.error().Message() <<
          ",requestId:" << outcome.error().RequestId() << std::endl;
      return ;
  }
  else {
      for (const auto& object : outcome.result().ObjectSummarys()) {

          QFileInfo fileInfo(QString::fromStdString(object.Key()));
          filename = fileInfo.fileName();
          if (!filename.isEmpty()) {
              filenames.append(filename);
          } 
          std::cout << "object" <<
              ",name:" << object.Key() <<
              ",size:" << object.Size() <<
              ",lastmodify time:" << object.LastModified() << std::endl;
      }
  }
  ///这块的展示内容怎么获得呢？
  ///1.首先请求该路径下的所有文件信息，需要得到文件名信息，患者信息，医生信息，做的修复类型信息
 
  model = new QStandardItemModel(this);
  //需要为每一行文件增添一个QStanditem对象
  for (int i = 0; i < filenames.count(); i++) {
      QStandardItem* item = new QStandardItem;
      item->setText(filenames.at(i));
      //item->setIcon(QIcon(":/image/floder.png"));
      model->appendRow(item);
  }
  // 将模型设置到 listView 中
  ui->listView->setModel(model);
  // 设置为垂直列表模式
  ui->listView->setViewMode(QListView::ListMode);
  // 显示 listView
  ui->listView->show();
}
void Book::urlbtn_clicked(){
    //设置下载文件资源的url，获取文件名，获取文件的大小
    QUrl url = ui->urledit->text();
    QString path = url.path();
    QFileInfo fileInfo(path);
    filename = fileInfo.fileName();
    qDebug() << "url:" << url;
    qDebug() << "文件名：" << filename;
    filenames.push_back(filename);
    //DownloadFilePath = QString(CheckpointFilePath + "/" + filename).toStdString();
    //getFileSize();
    //新增文件后的显示代码
    //fileListShow();
}



void Book::filepathbtn_clicked(){
    QString filename;//选择下载的文件夹
    QUrl filepath1 = QFileDialog::getExistingDirectoryUrl(this, tr("open file"), QUrl(""), QFileDialog::ShowDirsOnly);
    //CheckpointFilePath = filepath1.toString();
    //CheckpointFilePath = filepath.remove("file:///");
    //ui->filepathedit->setText(CheckpointFilePath);
}
